
#include "myopenglwidget.h"

#define timeOutmSec 500
#define AHEAD_TIME  200

float planeVertices[] = {
    // positions          // texture Coords (note we set these higher than 1 (together with GL_REPEAT as texture wrapping mode). this will cause the floor texture to repeat)
     50.0f, 0.0f,  100.0f,  1.0f, 0.0f,
    -50.0f, 0.0f,  100.0f,  0.0f, 0.0f,
    -50.0f, 0.0f, -100.0f,  0.0f, 1.0f,

     50.0f, 0.0f,  100.0f,  1.0f, 0.0f,
    -50.0f, 0.0f, -100.0f,  0.0f, 1.0f,
     50.0f, 0.0f, -100.0f,  1.0f, 1.0f
};

float lineVertices[] = {
    // positions          // texture Coords (note we set these higher than 1 (together with GL_REPEAT as texture wrapping mode). this will cause the floor texture to repeat)

    -0.1f, 0.0f,  0.0f,
    0.5f, 0.0f, -0.0f,

#if 0
    0.1f,  0.1f,  100.0f,  1.0f, 0.0f,
    -0.1f, 0.1f,  100.0f,  0.0f, 0.0f,
    -0.1f, 0.1f, -100.0f,  0.0f, 1.0f,

     0.1f, 0.1f,  100.0f,  1.0f, 0.0f,
    -0.1f, 0.1f, -100.0f,  0.0f, 1.0f,
     0.1f, 0.1f, -100.0f,  1.0f, 1.0f
#endif
};

QVector<QVector3D> cubePositions= {
    QVector3D(-30.0f, 0.1f, 0.0f),

    QVector3D(-10.0f, 0.1f, 0.0f),
    QVector3D( 10.0f, 0.1f, 0.0f),
    QVector3D( 30.0f, 0.1f, 0.0f)
};
#if 0
float vertices[] = {
    0.0f, 0.1f,  50.0f,
    0.0f, 0.1f, -100.0f,

    10.0f, 0.1f,  50.0f,
    10.0f, 0.1f, -100.0f,

    20.0f, 0.1f, -100.0f,
};
#endif
vector<float> vertices;


QVector3D lightPos(1.2f, 1.0f, 2.0f);
QVector3D lightColor(1.0f, 1.0f, 1.0f);
QVector3D objectColor(1.0f, 0.5f, 0.31f);
QVector3D viewInitPos(0.0,10.0,90.0);//
MyOpenglWidget::MyOpenglWidget(QWidget *parent)
    : QOpenGLWidget{parent}
{
    connect(&m_timer,&QTimer::timeout,this,&MyOpenglWidget::on_timeOut);
    m_timer.start(timeOutmSec);
//    m_timer.setSingleShot(true);

    m_time.start();
    m_camera.Position = viewInitPos;

    setFocusPolicy(Qt::StrongFocus);

    file.setFileName(":/images/images/1.txt");
    if(file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        //in(&file);
    }
}

MyOpenglWidget::~MyOpenglWidget()
{
    for(auto iter=m_Models.begin();iter!=m_Models.end();iter++)
    {
        ModelInfo *modelInfo=&iter.value();
        delete modelInfo->model;
    }

    if(file.isOpen())
        file.close();
}

void MyOpenglWidget::loadModel(string path)
{
    static int i = 0;
    makeCurrent();

    Model *_model = new Model(path.c_str());

    for(unsigned int i = 0; i < _model->meshes.size(); i++)
    {
        setupMesh(_model->meshes[i],_model->meshes[i].VAO, _model->meshes[i].VBO, _model->meshes[i].EBO);//, VAO, VBO, EBO
    }

    //m_camera.Position = getCameraInitPos(_model->m_minY,_model->m_maxY);
    m_Models ["张三"+QString::number(i++)] =
        ModelInfo{_model,QVector3D(0,0,0),0.0,0.0,0.0,false,"张三"};

    doneCurrent();
}

void MyOpenglWidget::setupMesh(const Mesh &mesh, unsigned int &VAO, unsigned int &VBO, unsigned int &EBO)
{
#if 1
    //创建VBO和VAO对象，并赋予ID
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1,&EBO);
    //绑定VBO和VAO对象
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    //为当前绑定到target的缓冲区对象创建一个新的数据存储。
    //如果data不是NULL，则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER, mesh.vertices.size()*sizeof(Vertex),
                 &(mesh.vertices[0]), GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                 mesh.indices.size() * sizeof(unsigned int),&(mesh.indices[0]), GL_STATIC_DRAW); //告知显卡如何解析缓冲里的属性值
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
    glEnableVertexAttribArray(2);
#endif
}


void MyOpenglWidget::initializeGL()
{
    initializeOpenGLFunctions();

    bool success;

    line_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shaders/shaders/line.vert");
    line_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shaders/shaders/line.frag");
    success = line_shaderProgram.link();
    if(!success)
    {
        qDebug()<<"Error:"<<line_shaderProgram.log();
    }
    line_shaderProgram.bind();

    //bool success;
    m_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shaders/shaders/shapes.vert");
    m_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shaders/shaders/shapes.frag");
    success=m_shaderProgram.link();
    if(!success) qDebug()<<"ERR:"<<m_shaderProgram.log();

    m_lightShaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shaders/shaders/light.vert");
    m_lightShaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shaders/shaders/light.frag");
    success=m_lightShaderProgram.link();
    if(!success) qDebug()<<"ERR:"<<m_lightShaderProgram.log();

    QOpenGLTexture *m_PlaneDiffuseTex=new
            QOpenGLTexture(QImage(":/images/images/wall.png").mirrored());


    m_PlaneMesh = processMesh(planeVertices,6,m_PlaneDiffuseTex->textureId());
    m_LineMesh = processMesh(lineVertices,6,0);



    //init_line();

    //创建VBO和VAO对象，并赋予ID
    glGenVertexArrays(1,&VAO);
    glGenBuffers(1,&VBO);
#if 0
    //绑定VAO和VBO对象
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);

    //为当前绑定到target的缓冲区对象创建一个新的数据存储。
    //如果data不是NULL，则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    //告知显卡如何解析缓冲里的属性值
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void *)0);
    //开启VAO管理的第一个属性值
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER,0);

    glBindVertexArray(0);
#endif

    loadModel(string("./nanosuit/nanosuit.obj"));
    /*
    loadModel(string("./nanosuit/nanosuit.obj"));
    loadModel(string("./nanosuit/nanosuit.obj"));
    loadModel(string("./nanosuit/nanosuit.obj"));
    loadModel(string("./nanosuit/nanosuit.obj"));
    loadModel(string("./nanosuit/nanosuit.obj"));
*/
    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &MyOpenglWidget::goAhead);
    timer->start(AHEAD_TIME);
}

void MyOpenglWidget::init_line()
{
    //绑定VAO和VBO对象
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);

    //为当前绑定到target的缓冲区对象创建一个新的数据存储。
    //如果data不是NULL，则使用来自此指针的数据初始化数据存储
    //glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
    glBufferData(GL_ARRAY_BUFFER,vertices.size()*sizeof(float),&(vertices[0]),GL_STATIC_DRAW);

    //告知显卡如何解析缓冲里的属性值
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,7*sizeof(float),(void *)0);
    //开启VAO管理的第一个属性值
    glEnableVertexAttribArray(0);

    //告知显卡如何解析缓冲里的属性值
    glVertexAttribPointer(1,4,GL_FLOAT,GL_FALSE,7*sizeof(float),(void *)(3*sizeof(float)));
    //开启VAO管理的第三个属性值
    glEnableVertexAttribArray(1);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

    glBindBuffer(GL_ARRAY_BUFFER,0);

    glBindVertexArray(0);
}

void MyOpenglWidget::resizeGL(int w, int h)
{
    Q_UNUSED(w);
    Q_UNUSED(h);
}

void MyOpenglWidget::paintGL()
{
#if 1
    QMatrix4x4 model;
    QMatrix4x4 view;
    QMatrix4x4 projection;

    //float time=m_time.elapsed()/50.0;

    projection.perspective(m_camera.Zoom,(float)width()/height(),0.1,10000);//10000
    view=m_camera.GetViewMatrix();

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    m_shaderProgram.bind();
    //m_shaderProgram.setUniformValue("light.position",lightPos);
    m_shaderProgram.setUniformValue("viewPos",m_camera.Position);
    m_shaderProgram.setUniformValue("projection", projection);
    m_shaderProgram.setUniformValue("view", view);
    //model.rotate(1.0f, 1.0f, 1.0f, 0.5f);
    m_shaderProgram.setUniformValue("model", model);

    // light properties, note that all light colors are set at full intensity
    m_shaderProgram.setUniformValue("light.ambient", 0.4f, 0.4f, 0.4f);
    m_shaderProgram.setUniformValue("light.diffuse", 0.9f, 0.9f, 0.9f);
    m_shaderProgram.setUniformValue("light.specular", 1.0f, 1.0f, 1.0f);
    // material properties
    m_shaderProgram.setUniformValue("material.shininess", 32.0f);
    m_shaderProgram.setUniformValue("light.direction", -0.2f, -1.0f, -0.3f);
#if 1
    {
        unsigned int diffuseNr = 1;
        unsigned int specularNr = 1;

        for(unsigned int i = 0; i < m_PlaneMesh->textures.size(); i++)
        {
            glActiveTexture(GL_TEXTURE0 + i);
            string number;
            string name = m_PlaneMesh->textures[i].type;
            if(name == "texture_diffuse")
                number = std::to_string(diffuseNr++);
            else if(name == "texture_specular")
                number = std::to_string(specularNr++);
            m_shaderProgram.setUniformValue(("material." + name + number).c_str(), i);
            glBindTexture(GL_TEXTURE_2D, m_PlaneMesh->textures[i].id);
        }

        glBindVertexArray(m_PlaneMesh->VAO);
        glDrawElements(GL_TRIANGLES, m_PlaneMesh->indices.size(), GL_UNSIGNED_INT, 0);
        //glDrawArrays(GL_TRIANGLES, 0, m_PlaneMesh.vertices.size());
        glBindVertexArray(0);
    }
#endif
    QMutexLocker mutex(&model_mutex);
    foreach(auto modelInfo,m_Models)
    {
        model.setToIdentity();

        model.translate(modelInfo.worldPos);
        model.rotate(modelInfo.pitch,QVector3D(1.0,0.0,0.0));
        model.rotate(modelInfo.yaw,QVector3D(0.0,1.0,0.0));
        model.rotate(modelInfo.roll,QVector3D(0.0,0.0,1.0));

        m_shaderProgram.bind();
        m_shaderProgram.setUniformValue("model", model);
        //modelInfo.model->Draw(m_shaderProgram);
        for(unsigned int i = 0; i < modelInfo.model->meshes.size(); i++)
        {
            //unsigned int VAO, VBO, EBO;
            unsigned int diffuseNr = 1;
            unsigned int specularNr = 1;

            for(unsigned int i = 0; i < modelInfo.model->meshes[i].textures.size(); i++)
            {
                glActiveTexture(GL_TEXTURE0 + i);
                string number;
                string name = modelInfo.model->meshes[i].textures[i].type;
                if(name == "texture_diffuse")
                    number = std::to_string(diffuseNr++);
                else if(name == "texture_specular")
                    number = std::to_string(specularNr++);
                m_shaderProgram.setUniformValue(("material." + name + number).c_str(), i);
                glBindTexture(GL_TEXTURE_2D, modelInfo.model->meshes[i].textures[i].id);
            }

            glBindVertexArray(modelInfo.model->meshes[i].VAO);
            glDrawElements(GL_TRIANGLES, modelInfo.model->meshes[i].indices.size(), GL_UNSIGNED_INT, 0);
            //glDrawArrays(GL_TRIANGLES, 0, m_model->meshes[i].vertices.size());
            glBindVertexArray(0);
        }

        m_shaderProgram.release();
    }
#endif

    line_shaderProgram.bind();
    //projection.perspective(m_camera.Zoom,(float)width()/(height()),0.1,100.0);
    line_shaderProgram.setUniformValue("projection", projection);
    line_shaderProgram.setUniformValue("view", view);

#if 0
    //glLineWidth(10.0);
    if(vertices.size() > 0)
    {
        qDebug() << "line";
        init_line();

        glBindVertexArray(VAO);

        model.setToIdentity();
        model.translate(QVector3D( 10.0f, 0.1f, 0.0f));

        line_shaderProgram.setUniformValue("model", model);
        glDrawArrays(GL_LINES, 0, vertices.size());
    }
    glBindVertexArray(0);
#else
#if 0
    //glDrawArrays(GL_TRIANGLES, 0, 3);
    model.setToIdentity();
    line_shaderProgram.setUniformValue("model", model);
    glDrawArrays(GL_LINES,0,6); //GL_LINES  GL_TRIANGLES
#else

    //glLineWidth(10.0);
    if(vertices.size() > 0)
    {
        init_line();

        glBindVertexArray(VAO);
//glPointSize(5.0);
        glLineWidth(5.0);
        QMutexLocker mutex(&line_mutex);
        foreach (auto item, cubePositions)
        {
            model.setToIdentity();
            model.translate(item);

            m_lightShaderProgram.setUniformValue("model", model);
            //glDrawElements(GL_TRIANGLES, m_LineMesh->indices.size(), GL_UNSIGNED_INT, 0);
            //glDrawArrays(GL_LINES, 0, m_LineMesh->vertices.size());
            glDrawArrays(GL_LINE_STRIP, 0, vertices.size());//GL_LINES  GL_POINTS GL_LINE_LOOP GL_LINE_STRIP
        }
        glBindVertexArray(0);
    }

#endif

#endif
}

void MyOpenglWidget::on_timeOut()
{
    int i = 0;

    QMutexLocker mutex(&model_mutex);
    for (QMap<QString, ModelInfo>::iterator it = m_Models.begin(); it != m_Models.end(); ++it)
    {
        ModelInfo *modelInfo = &it.value();
        //it->setValue(3); // 修改键为"apple"的元素值

        if(modelInfo)
        {
            int x = modelInfo->worldPos.x();
            if(x >= 40)
            {
                int z = modelInfo->worldPos.z();
                if(z >= 70)
                {
                    z = -100;
                }
                modelInfo->worldPos.setX(-50);
                modelInfo->worldPos.setZ(z+10);


            }
            else
            {
                x += 1;
                modelInfo->worldPos.setX(x);
            }
        }

        i++;
    }

    float c0=0, c1=0, c2=0, c3=0;
    float start = 0;
    float end = 0;
    if(file.isOpen())
    {
        vertices.clear();
        QList<QPointF> line_v;
        line_v.clear();
        if (!file.atEnd())
        {
            QString line = file.readLine();

            qDebug() << line;

            QStringList list = line.split(' ');
            int i = 0;

            for(QString s : list)
            {
                if(!s.isEmpty())
                {
                    bool flag = false;
                    QString str = s.mid(s.lastIndexOf("=")+1);
                    if(i ==0)
                    {
                        start = str.toDouble(&flag);
                    }
                    else if(i ==1)
                    {
                        end = str.toDouble(&flag);
                    }
                    else if(i ==2)
                    {
                        c0 = str.toDouble(&flag);
                    }
                    else if(i ==3)
                    {
                        c1 = str.toDouble(&flag);
                    }
                    else if(i ==4)
                    {
                        c2 = str.toDouble(&flag);
                    }
                    else if(i ==5)
                    {
                        c3 = str.toDouble(&flag);
                    }
                    if(!flag)
                    {
                        qDebug() << "fail:" <<str << " " << i;
                        flag = false;
                    }

                    i++;
                }
            }

            qDebug("start=%f  end=%f  c0==%f  c1=%f  c2=%f  c3=%f",
                   start, end, c0, c1, c2, c3);

            //double tmp = 10.0;
            double z = -100.0;
            int count = 0;
            int index = 0;
            bool flag = true;
            QMutexLocker mutex(&line_mutex);
            while(1)
            {
                double x = c3 *z*z*z + c2 *z*z + c1 *z + c0;

                //if(!((x-tmp<0.0000001) && (tmp-x<0.0000001)))//用相对误差计算，看两者是否相等；
                {
                    //line_v.append(QPointF(x, -z));//
                    vertices.push_back(x);
                    vertices.push_back(0.1);
                    vertices.push_back(z);

                    //color
                    if(flag)
                    {
                        vertices.push_back(1.0);
                        vertices.push_back(0.0);
                        vertices.push_back(0.0);
                        vertices.push_back(1.0);
                    }
                    else
                    {
                        vertices.push_back(0.0);
                        vertices.push_back(1.0);
                        vertices.push_back(0.0);
                        vertices.push_back(1.0);
                    }
                    //tmp = x;

                    count++;
                    if(count > 4)
                    {
                        count = 0;
                        flag = !flag;

                        index++;
                        if(index > 4)
                            index = 0;
                    }
                }

                z += 1.0;
                if(z >= 100.0)
                    break;
            }
            /*
            for(int z= -50; z<200; z+=1.0)//int z= start; z<end*10; z+=1.0
            {
                double x = c3 *z*z*z + c2 *z*z + c1 *z + c0;

                //if(tmp != x)
                if(!((x-tmp<0.0000001) && (tmp-x<0.0000001)))//用相对误差计算，看两者是否相等；
                {
                    line_v.append(QPointF(x, -z));//
                    //vertices.push_back(x);
                    //vertices.push_back(0.1);
                    //vertices.push_back(z);

                    tmp = x;
                }
            }*/
#if 0
            if(line_v.size() <= 2)
            {
                for(int i=0; i<line_v.size(); i++)
                {
                    vertices.push_back(line_v.at(i).x());
                    vertices.push_back(0.0);
                    vertices.push_back(line_v.at(i).y());
                }
            }
            else
            {

                int i = 0;
                while(i < line_v.count())
                {
                    if(i+3 <= line_v.count())//按照顺序进行贝塞尔曲线处理，并添加到绘图路径中
                    {
                        vertices.push_back(line_v.at(i).x());
                        vertices.push_back(0.0);
                        vertices.push_back(line_v.at(i).y());


#if 0
                        float tmp = 0.1;
                        while(1)
                        {
                            QPoint p = getPoint(line_v.at(i), line_v.at(i+1), line_v.at(i+2), tmp);
                            vertices.push_back(p.x());
                            vertices.push_back(0.0);
                            vertices.push_back(p.y());

                            tmp += 0.1;

                            if(tmp > 1.0)
                                break;
                        }
#else
                        vertices.push_back(line_v.at(i).x());
                        vertices.push_back(0.0);
                        vertices.push_back(line_v.at(i).y());

                        vertices.push_back(line_v.at(i+1).x());
                        vertices.push_back(0.0);
                        vertices.push_back(line_v.at(i+1).y());

                        vertices.push_back(line_v.at(i+2).x());
                        vertices.push_back(0.0);
                        vertices.push_back(line_v.at(i+2).y());
#endif

                    }
                    else
                    {
                        int a = i;
                        while (a < line_v.size())
                        {
                            vertices.push_back(line_v.at(a).x());
                            vertices.push_back(0.0);
                            vertices.push_back(line_v.at(a).y());
                            a++;
                        }
                    }

                    i = i+2;
                }

            }
#endif
           //static int count = 0;
           //count++;

           //if(count >= 5)m_timer.stop();

        }
        else
            file.close();
    }

    qDebug() << "size = " << vertices.size();
    update();
}

QVector3D MyOpenglWidget::getCameraInitPos(float min, float max)
{
    QVector3D temp={0.0,0.0,0.0};

    float height=max-min;
    temp.setZ(1.5*height);
    if(min>=0)
        temp.setY(height/2.0);
    viewInitPos=temp;
    return temp;
}

void MyOpenglWidget::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::RightButton){
        static QPoint lastPos(width()/2,height()/2);
        auto currentPos=event->pos();
        QPoint deltaPos=currentPos-lastPos;
        lastPos=currentPos;
        m_camera.ProcessMouseMovement(deltaPos.x(),-deltaPos.y());
    }
}

void MyOpenglWidget::wheelEvent(QWheelEvent *event)
{
    m_camera.ProcessMouseScroll(event->angleDelta().y()/120);
}

void MyOpenglWidget::keyPressEvent(QKeyEvent *event)
{
    float deltaTime=timeOutmSec/1000.0;
    switch(event->key())
    {
        case Qt::Key_W: m_camera.ProcessKeyboard(FORWARD,deltaTime);break;
        case Qt::Key_S: m_camera.ProcessKeyboard(BACKWARD,deltaTime);break;
        case Qt::Key_D: m_camera.ProcessKeyboard(RIGHT,deltaTime);break;
        case Qt::Key_A: m_camera.ProcessKeyboard(LEFT,deltaTime);break;
        case Qt::Key_Q: m_camera.ProcessKeyboard(DOWN,deltaTime);break;
        case Qt::Key_E: m_camera.ProcessKeyboard(UP,deltaTime);break;
        case Qt::Key_Space: m_camera.Position=viewInitPos;break;
    }
}

Mesh *MyOpenglWidget::processMesh(float *vertices, int size, unsigned int textureId)
{
    vector<Vertex> _vertices;
    vector<unsigned int> _indices;
    vector<Texture> _textures; //memcpy(&_vertices[0],vertices,5*size*sizeof(float));
    for(int i=0;i<size;i++){
        Vertex vert;
        vert.Position[0]=vertices[i*5+0];
        vert.Position[1]=vertices[i*5+1];
        vert.Position[2]=vertices[i*5+2];
        vert.TexCoords[0]=vertices[i*5+3];
        vert.TexCoords[1]=vertices[i*5+4];
        _vertices.push_back(vert);
        _indices.push_back(i);
    }
    Texture tex;
    tex.id=textureId;
    tex.type="texture_diffuse";
    _textures.push_back(tex);

    Mesh *mesh = new Mesh(_vertices,_indices,_textures);

    //创建VBO和VAO对象，并赋予ID
    glGenVertexArrays(1, &(mesh->VAO));
    glGenBuffers(1, &(mesh->VBO));
    glGenBuffers(1,&(mesh->EBO));
    //绑定VBO和VAO对象
    glBindVertexArray(mesh->VAO);
    glBindBuffer(GL_ARRAY_BUFFER, mesh->VBO);
    //为当前绑定到target的缓冲区对象创建一个新的数据存储。
    //如果data不是NULL，则使用来自此指针的数据初始化数据存储
    //qDebug() << vertices.size() << " " << sizeof(Vertex);

    glBufferData(GL_ARRAY_BUFFER, mesh->vertices.size()*sizeof(Vertex),
                           &(mesh->vertices[0]), GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                           mesh->indices.size() * sizeof(unsigned int),&(mesh->indices[0]), GL_STATIC_DRAW); //告知显卡如何解析缓冲里的属性值
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
    glEnableVertexAttribArray(1);

    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
    glEnableVertexAttribArray(2);

    return mesh;
    //return new Mesh(QOpenGLVersionFunctionsFactory::get<QOpenGLFunctions_3_3_Core>(QOpenGLContext::currentContext())
    //    ,_vertices,_indices,_textures);

}

QPoint MyOpenglWidget::getPoint(QPointF A,QPointF B,QPointF C,float t)
{
    int x = pow((1 - t), 2) * A.x() + 2 * t * (1 - t) * B.x() + pow(t, 2) * C.x();
    int y=pow((1 - t), 2) * A.y() + 2 * t * (1 - t) * B.y() + pow(t, 2) * C.y();
    return QPoint(x, y);
}

void MyOpenglWidget::goAhead()
{
    QMutexLocker m(&line_mutex);
    if(vertices.size() > 0)
    {
        static int step = 0;
        int index = 0;
        int offest = 0;

        for (vector<float>::iterator it = vertices.begin(); it != vertices.end(); it+=7)
        {
            float x= *(it+3);
            float tmp = 1.0;
            if(((x-tmp<0.0000001) && (tmp-x<0.0000001)))
            {
                *(it+3) = 0.0;
                *(it+4) = 1.0;
            }
            else
            {
                *(it+3) = 1.0;
                *(it+4) = 0.0;
            }
#if 0
            if(index >=step+offest && index<=step+offest+4)
            {
                *(it+3) = 1.0;
                *(it+4) = 0.0;
            }
            else
            {
                *(it+3) = 0.0;
                *(it+4) = 1.0;
            }

            index++;
            if(index >= step+offest+9)
            {
                offest += 10;
            }
#endif
        }

        step++;
        if(step > 4)
            step = 0;
    }
    update();
}
